package com.core.cloudbusiness.system.log.service.impl;

import com.core.cloudcommon.utils.IdUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.cloudbusiness.system.log.mapper.LoginLogMapper;
import com.core.cloudbusiness.system.log.service.LoginLogService;
import com.core.cloudcommon.CommonPageResponse;
import com.core.cloudcommon.security.LoginSecurityManager;
import com.core.cloundbusinessapi.system.log.dto.LoginLogDTO;
import com.core.cloundbusinessapi.system.log.vo.LoginLogQueryVO;
import com.core.cloundbusinessapi.system.login.vo.CloudSystemLoginVO;
import com.core.cloundbusinessapi.system.user.dto.CloudSystemUserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author =====Lqj=====
 * @className LoginLogServiceImpl
 * @description 登录日志服务实现
 * @create 2024/12/16 13:30
 **/
@Slf4j
@Service
public class LoginLogServiceImpl implements LoginLogService {

    @Autowired
    private LoginLogMapper loginLogMapper;

    @Autowired
    private LoginSecurityManager loginSecurityManager;

    // 移除Hutool的雪花算法，使用自定义的雪花ID生成器

    @Override
    public Long recordLoginLog(CloudSystemLoginVO loginVO, CloudSystemUserDTO userDTO, 
                              boolean success, String failReason, HttpServletRequest request, String token) {
        try {
            LoginLogDTO loginLog = new LoginLogDTO();
            
            // 设置基本信息
            loginLog.setId(IdUtils.generateSystemLogId());
            if (userDTO != null) {
                loginLog.setUserId(userDTO.getId());
                loginLog.setUserName(userDTO.getUserName());
                loginLog.setRealName(userDTO.getRealName());
            } else {
                // 登录失败时，从登录参数获取用户名
                loginLog.setUserName(loginVO.getUserName() != null ? loginVO.getUserName() : loginVO.getPhone());
            }
            
            // 设置登录信息
            loginLog.setLoginType(loginVO.getWay());
            loginLog.setLoginIp(loginSecurityManager.getClientIp(request));
            loginLog.setLoginTime(new Date());
            
            // 设置设备信息
            String deviceType = getDeviceTypeName(loginVO.getClientType());
            loginLog.setDeviceInfo(loginVO.getDeviceId(), loginVO.getDeviceName(), deviceType);
            
            // 设置浏览器和操作系统信息
            String userAgent = request.getHeader("User-Agent");
            loginLog.setBrowserAndOs(userAgent);
            
            // 设置其他请求信息
            loginLog.setReferer(request.getHeader("Referer"));
            
            // 设置登录结果
            if (success) {
                loginLog.setLoginSuccess(token);
            } else {
                loginLog.setLoginFail(failReason);
            }
            
            // 设置登录地址（可以集成IP地址库）
            loginLog.setLoginLocation(getLocationByIp(loginLog.getLoginIp()));
            
            // 保存到数据库
            loginLogMapper.insert(loginLog);
            
            log.info("记录登录日志成功，用户: {}, IP: {}, 结果: {}", 
                    loginLog.getUserName(), loginLog.getLoginIp(), success ? "成功" : "失败");
            
            return loginLog.getId();
            
        } catch (Exception e) {
            log.error("记录登录日志失败: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    @Async
    public void recordLoginLogAsync(CloudSystemLoginVO loginVO, CloudSystemUserDTO userDTO, 
                                   boolean success, String failReason, HttpServletRequest request, String token) {
        recordLoginLog(loginVO, userDTO, success, failReason, request, token);
    }

    @Override
    public void recordLogoutLog(String token, HttpServletRequest request) {
        try {
            LoginLogDTO loginLog = loginLogMapper.selectByToken(token);
            if (loginLog != null) {
                Date logoutTime = new Date();
                long sessionDuration = 0;
                if (loginLog.getLoginTime() != null) {
                    sessionDuration = (logoutTime.getTime() - loginLog.getLoginTime().getTime()) / (1000 * 60);
                }
                
                loginLogMapper.updateLogoutTime(token, logoutTime, sessionDuration);
                
                log.info("记录退出日志成功，用户: {}, 会话时长: {}分钟", 
                        loginLog.getUserName(), sessionDuration);
            }
        } catch (Exception e) {
            log.error("记录退出日志失败: {}", e.getMessage(), e);
        }
    }

    @Override
    public CommonPageResponse<LoginLogDTO> queryLoginLogs(LoginLogQueryVO queryVO) {
        Page<LoginLogDTO> page = new Page<>(queryVO.getPageNumber(), queryVO.getPageSize());
        IPage<LoginLogDTO> result = loginLogMapper.selectLoginLogPage(page, queryVO);
        
        CommonPageResponse<LoginLogDTO> response = new CommonPageResponse<>();
        response.setRecords(result.getRecords());
        response.setTotal(result.getTotal());
        response.setSize(result.getSize());
        response.setCurrent(result.getCurrent());
        response.setPages(result.getPages());
        
        return response;
    }

    @Override
    public LoginLogDTO getLoginLogById(Long id) {
        return loginLogMapper.selectById(id);
    }

    @Override
    public boolean deleteLoginLog(Long id) {
        return loginLogMapper.deleteById(id) > 0;
    }

    @Override
    public int batchDeleteLoginLogs(Long[] ids) {
        return loginLogMapper.batchDeleteByIds(ids);
    }

    @Override
    public int cleanExpiredLogs(int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -days);
        Date expireDate = calendar.getTime();
        
        int count = loginLogMapper.deleteExpiredLogs(expireDate);
        log.info("清理{}天前的登录日志，共清理{}条记录", days, count);
        
        return count;
    }

    @Override
    public List<LoginLogDTO> getRecentLoginLogs(Long userId, int limit) {
        return loginLogMapper.selectRecentLoginLogs(userId, limit);
    }

    @Override
    public long countLoginTimes(Long userId, Date startTime, Date endTime) {
        return loginLogMapper.countLoginTimes(userId, startTime, endTime);
    }

    @Override
    public Map<String, Object> getLoginStatistics(Date startTime, Date endTime) {
        Map<String, Object> statistics = new HashMap<>();
        
        try {
            // 基础统计
            long totalLogins = loginLogMapper.countSuccessLogins(startTime, endTime) + 
                              loginLogMapper.countFailLogins(startTime, endTime);
            long successLogins = loginLogMapper.countSuccessLogins(startTime, endTime);
            long failLogins = loginLogMapper.countFailLogins(startTime, endTime);
            long uniqueUsers = loginLogMapper.countUniqueUsers(startTime, endTime);
            
            statistics.put("totalLogins", totalLogins);
            statistics.put("successLogins", successLogins);
            statistics.put("failLogins", failLogins);
            statistics.put("uniqueUsers", uniqueUsers);
            statistics.put("successRate", totalLogins > 0 ? (double) successLogins / totalLogins * 100 : 0);
            
            // 设备类型统计
            List<Map<String, Object>> deviceStats = loginLogMapper.countByDeviceType(startTime, endTime);
            statistics.put("deviceStats", deviceStats);
            
            // 浏览器统计
            List<Map<String, Object>> browserStats = loginLogMapper.countByBrowser(startTime, endTime);
            statistics.put("browserStats", browserStats);
            
            // 操作系统统计
            List<Map<String, Object>> osStats = loginLogMapper.countByOs(startTime, endTime);
            statistics.put("osStats", osStats);
            
            // 地区统计
            List<Map<String, Object>> locationStats = loginLogMapper.countByLocation(startTime, endTime);
            statistics.put("locationStats", locationStats);
            
            // 失败IP统计
            List<Map<String, Object>> topFailIps = loginLogMapper.getTopFailIps(startTime, endTime, 10);
            statistics.put("topFailIps", topFailIps);
            
        } catch (Exception e) {
            log.error("获取登录统计信息失败: {}", e.getMessage(), e);
        }
        
        return statistics;
    }

    /**
     * 获取设备类型名称
     */
    private String getDeviceTypeName(Integer clientType) {
        if (clientType == null) {
            return "未知";
        }
        switch (clientType) {
            case 0: return "Web端";
            case 1: return "iOS端";
            case 2: return "安卓端";
            case 3: return "Windows端";
            case 4: return "macOS端";
            case 5: return "鸿蒙端";
            default: return "未知设备";
        }
    }

    /**
     * 根据IP获取地理位置
     * 这里可以集成第三方IP地址库，如高德、百度等
     */
    private String getLocationByIp(String ip) {
        // 简单实现，实际项目中应该集成IP地址库
        if (ip == null || "127.0.0.1".equals(ip) || "localhost".equals(ip)) {
            return "本地";
        }
        
        // 内网IP
        if (ip.startsWith("192.168.") || ip.startsWith("10.") || ip.startsWith("172.")) {
            return "内网";
        }
        
        // 这里可以调用第三方API获取真实地理位置
        return "未知地区";
    }
}
